package com.lizi.core.util;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.apache.commons.beanutils.BeanUtils;

/**
 * Bean工具类
 */
public class BeanUtil  {
	
	
	  public static Object mapToObject_reflect(Map<String, Object> map, Class<?> beanClass) throws Exception {    
	        if (map == null)  
	            return null;    
	  
	        Object obj = beanClass.newInstance();  
	  
	        Field[] fields = obj.getClass().getDeclaredFields();   
	        Object val = null;
	        for (Field field : fields) {    
	            int mod = field.getModifiers();    
	            if(Modifier.isStatic(mod) || Modifier.isFinal(mod)){    
	                continue;    
	            }    
	            val = map.get(field.getName());
	            if(val != null){
	            	field.setAccessible(true);    
		            field.set(obj, map.get(field.getName()));   
	            } 
	        }   
	  
	        return obj;    
	    }    
	  
	    public static Map<String, Object> objectToMap_reflect(Object obj) throws Exception {    
	        if(obj == null){    
	            return null;    
	        }   
	  
	        Map<String, Object> map = new HashMap<String, Object>();    
	  
	        Field[] declaredFields = obj.getClass().getDeclaredFields();    
	        for (Field field : declaredFields) {    
	            field.setAccessible(true);  
	            map.put(field.getName(), field.get(obj));  
	        }    
	  
	        return map;  
	    }   
	
	public static Object mapToObject_Introspector(Map<String, Object> map, Class<?> beanClass) throws Exception {    
        if (map == null)   
            return null;    
  
        Object obj = beanClass.newInstance();  
  
        BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());    
        PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();    
        Object val;
        for (PropertyDescriptor property : propertyDescriptors) { 
        	val = map.get(property.getName());
        	if(val == null){
        		continue;
        	}
            Method setter = property.getWriteMethod();    
            if (setter != null) {  
                setter.invoke(obj, val);   
            }  
        }  
  
        return obj;  
    }    
      
    public static Map<String, Object> objectToMap_Introspector(Object obj) throws Exception {    
        if(obj == null)  
            return null;      
  
        Map<String, Object> map = new HashMap<String, Object>();   
  
        BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());    
        PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();    
        for (PropertyDescriptor property : propertyDescriptors) {    
            String key = property.getName();    
            if (key.compareToIgnoreCase("class") == 0) {   
                continue;  
            }  
            Method getter = property.getReadMethod();  
            Object value = getter!=null ? getter.invoke(obj) : null;  
            map.put(key, value);  
        }    
  
        return map;  
    }    
	
    public static <T> T map2Bean(Map<String, Object> map,Class<T> clazz) throws Exception  {
        if (map == null) {
            return null;
        }

        T bean = null;
        
            bean = clazz.newInstance();
            BeanUtils.populate(bean,map);
       
        return bean;
    }  
      
    public static Map<?, ?> beanToMap(Object obj) {  
        if(obj == null)  
            return null;   
        return new org.apache.commons.beanutils.BeanMap(obj);  
    }    
	 
   
    /**
     *
     * 将 Domain 转换为 Map
     *
     * @param t
     * @param <T>
     * @return
     * @throws IllegalAccessException
     * @throws NoSuchMethodException
     * @throws InvocationTargetException
     *@return Map<String, String>
     */
    public static <T> Map toMap(T t) throws IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        return BeanUtils.describe(t);
    }

    /**
     * @param obj
     * @return Map<String, Object>
     */
    public static Map<String, Object> bean2Map(Object obj) {
        if(obj == null){
            return null;
        }
        Map<String, Object> map = new HashMap<String, Object>();
        Field[] fields = obj.getClass().getDeclaredFields();
        for (int i = 0, len = fields.length; i < len; i++) {
            String varName = fields[i].getName();
            try {
                boolean accessFlag = fields[i].isAccessible();
                fields[i].setAccessible(true);
                Object o = fields[i].get(obj);
                if (o != null){map.put(varName, o);}
                fields[i].setAccessible(accessFlag);
            } catch (IllegalArgumentException ex) {
                ex.printStackTrace();
            } catch (IllegalAccessException ex) {
                ex.printStackTrace();
            }
        }
        return map;
    }

    public static List<Map<String, Object>> bean2MapList(List<Object> list){
        if(list == null || list.isEmpty()){
            return null;
        }
        List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();
        for(Object object: list){
            result.add(bean2Map(object));
        }
        return  result;
    }

    /**
     *
     * 将List<Domain>转换为List<Map>
     *
     * @param list
     * @param <T>
     * @return
     * @throws IllegalAccessException
     * @throws NoSuchMethodException
     * @throws InvocationTargetException
     *
     */
    public static <T> List<Map> toMapList(List<T> list) throws IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        List<Map> newList = new LinkedList<Map>();
        for (T t : list){
            newList.add(BeanUtils.describe(t));
        }
        return newList;
    }

    /**
     *  property属性目前需要为字符串
     * @param list
     * @param property
     * @return
     * @throws Exception
     */
    public static <T> List strPropertiesToList(List<T> list, String property ) throws Exception {
        List propertyList = new ArrayList();
        if(list == null || list.isEmpty()){
            return propertyList;
        }
        for (T t : list){
            String value = BeanUtils.getProperty(t, property);
            if (StringUtils.isNotEmpty(value)){
                propertyList.add(value);
            }
        }
        return propertyList;
    }

    /**
     * 将对象list转化成Map，property必须满足唯一性，同时是字符串
     * @param list
     * @param property
     * @return
     * @throws Exception
     */

    public static <T> Map listToMap(List<T> list, String property ) throws Exception  {
        Map map = new HashMap();
        if(list == null || list.isEmpty()){
            return map;
        }
        for (T t : list){
            String value = BeanUtils.getProperty(t, property);
            if (StringUtils.isNotEmpty(value)){
                map.put(value, t);
            }
        }
        return map;
    }



}
